package cs421;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class HttpRequest {

	private static final Pattern CHARSET_PATTERN = Pattern.compile(
			"\\bcharset=([\\w:-]+)\\b", Pattern.CASE_INSENSITIVE);
			
	Map<String, String> headers;

	Url url;
	byte[] 	contents;
	
	public HttpRequest(Url url) throws IOException {
		headers = new HashMap<String, String>();
		this.url = url;
	}

	public String workingPath() {
		return url.getHost() + ":" + url.getPort() + url.getPath();
	}
	
	public byte[] getContents() {
		return contents;
	}
	
	public boolean isHtml() {
		return headers.get("Content-Type").startsWith("text/html");
	}
	
	public Charset charset() {
		String cs = headers.get("Content-Type");
		Matcher m = CHARSET_PATTERN.matcher(cs);
		return m.find() ? Charset.forName(m.group(1))
				: Charset.defaultCharset();
	}
	
	public int contentsLength() {
		return Integer.valueOf(headers.get("Content-Length"));
	}
	
	public void send() throws IOException {
		
		Socket sk = new Socket(url.getHost(), url.getPort());

		sendRequest(sk.getOutputStream());
		
		DataInputStream is = new DataInputStream(sk.getInputStream());
		if(!getHeaders(is))
			throw new IOException("error getting headers");
		
		int cl = Integer.valueOf(headers.get("Content-Length"));
		contents = new byte[cl];
		/*int i = */is.readFully(contents);
		//System.out.printf("read %d bytes, size=%d%n", i, cl);
		sk.close();
	}

	private void sendRequest(OutputStream os) throws IOException {
		String req = "GET " + url.getPath() + url.getFile() + " HTTP/1.1\n" +
			"Host: " + url.getHost() + "\r\n\r\n";
		
		//System.out.println("requesting " + req);
		os.write(req.getBytes("US-ASCII"));
		os.flush();
	}
	
	private boolean getHeaders(InputStream is) throws IOException {

		StringBuilder sb = new StringBuilder();
		
		char c;
		while((c = (char) is.read()) != '\r')
			sb.append(c);
		is.skip(1);
		
		if(!sb.toString().matches("HTTP/\\d\\.\\d 200 OK"))
			return false;

		sb = new StringBuilder();
		while(true) {
			int i = is.read();
			if(i < 0)
				return false;
			
			c = (char) i;
			sb.append(c);
			if(c == '\r') {
				is.skip(1);

				String[] ss = sb.toString().split(":");
				if(ss.length < 2)
					break;
				//System.out.println(ss[0].trim() + ", " + ss[1].trim());
				headers.put(ss[0].trim(), ss[1].trim());
				sb = new StringBuilder();
			}
		}

		return true;
	}
	
	/*
	public static void main(String[] args) throws IOException {
		String url = "http://wlab.cs.bilkent.edu.tr/~alper/pa1/test.html";
		url = "http://www.ee.bilkent.edu.tr/~ee212/labs/Lab2.html";
		HttpRequest req = new HttpRequest(new Url(url));
		if(req.isHtml())
			System.out.printf(new String(req.getContents(), req.charset()));
	}
	*/
	
	/*
	@SuppressWarnings("serial")
	public static class HttpException extends IOException {
		public HttpException(String desc) {
			super(desc);
		}
	}

	@SuppressWarnings("serial")
	public static class ProtocolException extends HttpException {
		public ProtocolException() {
			super("Protcol not supportred");
		}
	}

	@SuppressWarnings("serial")
	public static class MalformedURLException extends HttpException {
		public MalformedURLException() {
			super("Malformed URL");
		}
	}
	 */

}
